/* -*- Mode: c; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
/*
  RefObject (http://code.google.com/p/refobject/)
  Copyright (C) 2010-2011 MIURA Shirow (sharow)
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <setjmp.h>
#include <cmockery.h>

#include <RefObject/RefObjectAll.h>
#include "test_common.h"


static void
test_RefBuildValue_Primitive0(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("i", 123);
    assert_true(RefInt_IsValid(o));
    assert_true(RefInt_AsInt(o) == 123);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List0(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("[]");
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 0);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List1(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("[i]", 1);
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 1);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 0)) == 1);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List2(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("[iii]", 1, 2, 3);
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 3);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 0)) == 1);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 1)) == 2);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 2)) == 3);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List3(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("[i, i,i]", 1, 2, 3);
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 3);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 0)) == 1);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 1)) == 2);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 2)) == 3);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List4(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("[ii,i]", 1, 2, 3);
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 3);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 0)) == 1);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 1)) == 2);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 2)) == 3);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_List_ErrorCase0(void **state)
{
    assert_true(RefBuildValueByVaArgs("[") == NULL);
    assert_true(RefBuildValueByVaArgs("]") == NULL);
    assert_true(RefBuildValueByVaArgs("[,]") == NULL);
    assert_true(RefBuildValueByVaArgs("[i,]", 1) == NULL);
    assert_true(RefBuildValueByVaArgs("[,i]", 1) == NULL);
    assert_true(RefBuildValueByVaArgs("[[]") == NULL);
    assert_true(RefBuildValueByVaArgs("[]]") == NULL);
}

static void
test_RefBuildValue_Dict0(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs(" { } ");
    assert_true(RefDict_IsValid(o));
    assert_true(RefDict_GetSize(o) == 0);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Dict1(void **state)
{
    RefObject *o;
    RefObject *r;

    o = RefBuildValueByVaArgs("{s:i}", "abc", 123);
    assert_true(RefDict_IsValid(o));
    assert_true(RefDict_GetSize(o) == 1);
    
    r = RefDict_GetItemCString(o, "abc", -1);
    assert_true(r);
    assert_true(RefInt_IsValid(r));
    assert_true(RefInt_AsInt(r) == 123);

    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Dict2(void **state)
{
    RefObject *o;
    RefObject *r;

    o = RefBuildValueByVaArgs("{s:i, 'def' : [i]}", "abc", 123, 456);
    assert_true(RefDict_IsValid(o));
    assert_true(RefDict_GetSize(o) == 2);
   
    r = RefDict_GetItemCString(o, "abc", -1);
    assert_true(r);
    assert_true(RefInt_IsValid(r));
    assert_true(RefInt_AsInt(r) == 123);

    r = RefDict_GetItemCString(o, "def", -1);
    assert_true(r);
    assert_true(RefList_IsValid(r));
    assert_true(RefList_GetSize(r) == 1);

    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Dict3(void **state)
{
    RefObject *o;
    RefObject *r;

    o = RefBuildValueByVaArgs(" { 'abc':i, 'def': [ ] } ", 123);
    assert_true(RefDict_IsValid(o));
    assert_true(RefDict_GetSize(o) == 2);
    
    r = RefDict_GetItemCString(o, "abc", -1);
    assert_true(r);
    assert_true(RefInt_IsValid(r));
    assert_true(RefInt_AsInt(r) == 123);

    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Dict_ErrorCase0(void **state)
{
    assert_true(RefBuildValueByVaArgs("{") == NULL);
    assert_true(RefBuildValueByVaArgs("}") == NULL);
    assert_true(RefBuildValueByVaArgs("{,}") == NULL);
    assert_true(RefBuildValueByVaArgs("{s:[],}", "a") == NULL);
    assert_true(RefBuildValueByVaArgs("{,s:[]}", "a") == NULL);
    assert_true(RefBuildValueByVaArgs("{[]:s,}", "a") == NULL);
    assert_true(RefBuildValueByVaArgs("{[{s:,}]}", "a") == NULL);
    assert_true(RefBuildValueByVaArgs("{s}", "a") == NULL);
    assert_true(RefBuildValueByVaArgs("{}}") == NULL);
    assert_true(RefBuildValueByVaArgs("{{}") == NULL);
}

static void
test_RefBuildValue_ValueTest0(void **state)
{
    RefObject *o;
    RefObject *v;

    v = RefInt_Create(1);
    o = RefBuildValueByVaArgs("O", v);
    RefObject_DecRef(v);
    v = NULL;

    assert_true(o);
    assert_true(RefInt_IsValid(o));
    assert_true(RefInt_AsInt(o) == 1);

    RefObject_DecRef(o);
}

static void
test_RefBuildValue_ValueTest1(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("s", "abc");
    assert_true(o);
    assert_true(RefString_IsValid(o));
    assert_true(strcmp(RefString_AsString(o), "abc") == 0);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_ValueTest2(void **state)
{
    RefObject *o;
    
    o = RefBuildValueByVaArgs("v", (void *)1);
    assert_true(o);
    assert_true(RefVoidPtr_IsValid(o));
    assert_true(RefVoidPtr_AsVoidPtr(o) == (void *)1);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_ValueTest3(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("f", 0.0);
    assert_true(o);
    assert_true(RefFloat_IsValid(o));
    assert_true(RefFloat_AsFloat(o) == 0.0);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_ValueTest4(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs("     i    ", 1);
    assert_true(o);
    assert_true(RefInt_IsValid(o));
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Complex0(void **state)
{
    RefObject *o;
    o = RefBuildValueByVaArgs(" [ { 'abc':[{'def':[ {} ]}] } ] ");
    assert_true(o);
    RefObject_DecRef(o);
}

static void
test_RefBuildValue_Complex1(void **state)
{
    RefObject *o1;

    {
        RefObject *o2;
        o2 = RefBuildValueByVaArgs(" [ i ] ", 123);
        assert_true(o2);
        o1 = RefBuildValueByVaArgs(" [ O ] ", o2);
        RefObject_DecRef(o2);
    }

    assert_true(o1);
    assert_true(RefList_IsValid(o1));
    assert_true(RefList_GetSize(o1) == 1);

    {
        RefObject *o2;
        RefObject *o3;
        o2 = RefList_GetItem(o1, 0);
        assert_true(RefList_IsValid(o2));
        assert_true(RefList_GetSize(o2) == 1);
        o3 = RefList_GetItem(o2, 0);
        assert_true(RefInt_IsValid(o3));
        assert_true(RefInt_AsInt(o3) == 123);
    }

    RefObject_DecRef(o1);
}

static void
test_RefBuildValue_ByRefList0(void **state)
{
    RefObject *o;
    RefObject *list;
    RefObject *value;

    value = RefInt_Create(123);
    list = RefList_Create();
    RefList_Append(list, value);
    RefList_Append(list, value);
    RefObject_DecRef(value);

    o = RefBuildValueByList(" [ii] ", list);
    RefObject_DecRef(list);

    assert_true(o);
    assert_true(RefList_IsValid(o));
    assert_true(RefList_GetSize(o) == 2);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 0)) == 123);
    assert_true(RefInt_AsInt(RefList_GetItem(o, 1)) == 123);

    RefObject_DecRef(o);
}

int
test_RefBuildValue(void)
{
    const UnitTest tests[] = {
        unit_test_setup_teardown(test_RefBuildValue_Primitive0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List1, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List2, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List3, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List4, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_List_ErrorCase0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Dict0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Dict1, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Dict2, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Dict3, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Dict_ErrorCase0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ValueTest0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ValueTest1, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ValueTest2, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ValueTest3, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ValueTest4, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Complex0, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_Complex1, setup, teardown),
        unit_test_setup_teardown(test_RefBuildValue_ByRefList0, setup, teardown),
        unit_test(null_test_success)
    };
    return run_tests(tests);
}

